package com.qingyun.form.internal.adapter

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.recyclerview.widget.RecyclerView
import com.qingyun.form.R
import com.qingyun.form.provider.FormDataProvider
import com.qingyun.form.entity.FormSelectItem

@SuppressLint("NotifyDataSetChanged")
internal class FormSelectAdapter(
    private val selectedItem: FormSelectItem?,
    private val provider: FormDataProvider,
    private val listener: ((FormSelectItem) -> Unit),
) : RecyclerView.Adapter<FormSelectViewHolder>(), View.OnClickListener, View.OnLongClickListener {
    companion object {
        private const val NAVIGATION_NAME = "FORM_NAVIGATION_NAME"
    }

    private val items = mutableListOf<FormSelectItem>()

    /** 导航 Item */
    private val navigationItem by lazy { FormSelectItem("", "", NAVIGATION_NAME) }

    init {
        setDataList(provider.getItems(selectedItem))
        if (selectedItem?.parent != null) {
            appendNavigationItem(selectedItem)
        }
    }

    private fun appendNavigationItem(item: FormSelectItem) {
        navigationItem.apply {
            value = item.value
            parent = item.parent
            label = provider.getNavigationTitle(item)

            items.add(0, this)
            notifyItemInserted(0)
        }
    }

    private fun setDataList(data: List<FormSelectItem>) {
        items.clear()
        items.addAll(data)
        notifyDataSetChanged()
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int,
    ): FormSelectViewHolder {
        return FormSelectViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.form_select_dialog_item,
                parent,
                false
            )
        )
    }

    override fun onBindViewHolder(
        holder: FormSelectViewHolder,
        position: Int,
    ) {
        val item = items[position]
        holder.itemView.isSelected = item == selectedItem
        holder.setLabel(item.label)
        holder.showArrow(item.hasChildren)
        holder.showBackArrow(item.isNavigation())
        holder.showCheckView(provider.enableCheckParent && item.isNavigation())
        holder.checkView.tag = position
        holder.checkView.setOnClickListener(this)
        holder.itemView.setOnClickListener(this)
        holder.itemView.setOnLongClickListener(this)
    }

    override fun getItemCount(): Int {
        return items.size
    }

    private fun FormSelectItem.isNavigation(): Boolean {
        return NAVIGATION_NAME == this.name
    }

    override fun onClick(v: View) {
        if (v.id == R.id.tvCheck) {
            val position = v.tag as Int
            onCheckClick(items[position].parent!!)
            return
        }

        val item = findItemByView(v) ?: return
        when {
            item.isNavigation() -> backToPreviousLevel(item)
            item.hasChildren -> goToNextLevel(item)
            else -> listener.invoke(item)
        }

    }

    private fun goToNextLevel(item: FormSelectItem) {
        if (!item.hasChildren) {
            return
        }
        val children = item.children ?: return
        setDataList(children)
        appendNavigationItem(children[0])
    }

    private fun backToPreviousLevel(item: FormSelectItem) {
        val parent = item.parent!!.parent ?: return setDataList(provider.getItems())
        setDataList(parent.children!!)
        appendNavigationItem(item.parent!!)
    }

    private fun findItemByView(view: View): FormSelectItem? {
        val position =
            (view.layoutParams as RecyclerView.LayoutParams).viewAdapterPosition
        if (position == RecyclerView.NO_POSITION) {
            return null
        }
        return items[position]
    }

    private fun onCheckClick(item: FormSelectItem) {
        provider.getItem(item.value)?.let {
            listener.invoke(it)
        }
    }

    override fun onLongClick(v: View): Boolean {
        val item = findItemByView(v) ?: return false
        Toast.makeText(v.context, item.label, Toast.LENGTH_SHORT).show()
        return true
    }
}